using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Gtk;

using Subsync;
using Subsync.Test;
using Subsync.Core.Sync;
using Subsync.Core.SvnServe;
using Subsync.GUI;

namespace Subsync.CLI
{
	/// <summary>
	/// Author: Steven Goh Jian Wen, except the methods with Author: Hoang Duc or Author: Juin Min
	/// </summary>
	public class Views
	{
		private Dictionary<string, List<object>> tokens = new Dictionary<string, List<object>> ();
		private List<KeyValuePair<string, App.initPointer>> dispatcher_triggers = new List<KeyValuePair<string, App.initPointer>> ();
		private List<App> installed_apps = new List<App> ();

		public static MainWindow main;
		public static AdvanceTop advwin;
		public static bool tray_minizable;
		
		//tokenize and initialized dispatch.
		public Views (string[] args)
		{
			//INSTALL APPS HERE.
			installed_apps.Add (new Subsync.Core.Subversion.CLIManager ());
			installed_apps.Add (new Subsync.Core.Sync.CLIManager ());
			installed_apps.Add (new Subsync.Core.Excludes.CLIManager ());
			installed_apps.Add (new Subsync.Core.SvnServe.CLIManager ());
			//INSTALL END
			
			foreach (App app in installed_apps) {
				foreach (KeyValuePair<string, List<object>> match in app.GetTokens ()) {
					tokens.Add (match.Key, match.Value);
				}
			}
			
			foreach (App app in installed_apps) {
				//For initdispatchers
				foreach (KeyValuePair<string, App.initPointer> m in app.GetInitPointers ()) {
					dispatcher_triggers.Add (m);
				}
			}
			
			//Start dispatch
			Dictionary<string, List<object>> tokenized = Tokenize (args);
			Dispatch (tokenized);
		}

		public void Dispatch (Dictionary<string, List<object>> tokenized_args)
		{
			//Loop and find the first match, then dispatch. Else load the default method.
			foreach (KeyValuePair<string, App.initPointer> m in dispatcher_triggers) {
				if (tokenized_args.ContainsKey (m.Key)) {
					m.Value (tokenized_args);
					return;
				}
			}
			
			//Default dispatch
			this.DefaultAction ();
		}

	/// <summary>
	/// Author: Hoang Duc
	/// </summary>
		public Dictionary<string, List<object>> Tokenize (string[] args)
		{
			Dictionary<string, List<object>> ret = new Dictionary<string, List<object>> ();
			string current_token_name = null;
			string argBuffer = "";
			
			foreach (string s in args) {
				if (s.ToCharArray ()[0] == '-') {
					string token_keyword;

					if (s.ToCharArray ()[1] == '-')
						token_keyword = s.Split ('-')[2];
					else
						token_keyword = s.Split ('-')[1];
					
					//Lets try to find it in Tokens
					foreach (KeyValuePair<string, List<object>> match in tokens) {
						string token_name = match.Key;
						List<object> token_args_list = match.Value;
						if (token_args_list.Contains (token_keyword)) {
							ret.Add (token_name, new List<object> ());
							current_token_name = token_name;
						}
					}
				}
                else if (current_token_name != null) {
					argBuffer += s;
					bool completeArg = true;
					//the next param is an arg, lets save it.
					if (s.StartsWith ("\"")) {
						completeArg = false;
						if (s.EndsWith ("\""))
							completeArg = true;
					}
                    else if (s.StartsWith ("'")) {
						completeArg = false;
						if (s.EndsWith ("'"))
							completeArg = true;
					}
					
					if (completeArg) {
						ret[current_token_name].Add (argBuffer);
						argBuffer = "";
					}
					continue;
				}
			}
			return ret;
		}

		[DllImport("user32.dll")]
		public static extern IntPtr FindWindow (string lpClassName, string lpWindowName);

		[DllImport("user32.dll")]
		static extern bool ShowWindow (IntPtr hWnd, int nCmdShow);

		public void DefaultAction ()
		{
			Gtk.StatusIcon tray_icon;
			tray_icon = null;
			//Disable console
			SetConsoleWindowVisibility (false, Console.Title);
			
			Debug.WriteLine ("Init: No switches found, loading GUI.");
			Application.Init ();
			
			tray_minizable = Subsync.Tools.StringToBool (new Config ().GetProperty ("MinimizeTray"));
			if (tray_minizable) {
			
				string img_path = new Config ().GetProperty ("ImageStoragePath");
				string icon_path = System.IO.Path.Combine (img_path, "trayicon.ico");
				tray_icon = new Gtk.StatusIcon (icon_path);
			
				tray_icon.Visible = true;
				tray_icon.Activate += HandleTray_iconActivate;
			}
			
			List<Sync> list_of_syncs = new Config ().GetAllSyncs ();
			if (list_of_syncs.Count > 0) {
				main = new MainWindow ();
				main.Show ();
			}
            else {
				advwin = new AdvanceTop ();
				advwin.Show ();
			}
			Application.Run ();
			if (tray_icon!=null)
				tray_icon.Dispose ();
			Debug.WriteLine ("Init: GUI closed, ending application");
		}
		
		/// <summary>
		/// We handle startup stuff here. 
		/// </summary>
		public static void HandleStartup ()
		{
			Config c = new Config ();
			SvnServe svnserver = new SvnServe ();
			bool start_svnserve_automatically = Subsync.Tools.StringToBool (c.GetProperty ("ManualSVNServe"));
			
			if (!svnserver.IsServiceInstalled ()) {
				svnserver.InstallWindowsService (c.GetProperty ("SVNServePath"));
				//wait for 2 ticks for installation to work out
				System.Threading.Thread.Sleep (new System.TimeSpan(2));
			}
			
			try {
				if (start_svnserve_automatically) {
					if (!svnserver.IsActive ()) {
						svnserver.Start ();
					}
				} else {
					if (svnserver.IsActive ()) {
						svnserver.Stop ();
					}
				}
			} catch (Exception) {
			}
		
		}
		
		public static void HandleShutdown ()
		{
			SvnServe svnserver = new SvnServe ();
			try {
				if (svnserver.IsActive ()) {
					svnserver.Stop ();
				}
				
			} catch (Exception) {
			}
		}

		/// <summary>
		/// Author: Juin Min
		/// </summary>
		void HandleTray_iconActivate (object sender, EventArgs e)
		{
			if (main != null){
				if (main.Visible){
					main.Deiconify ();
				}else{
					main.Show ();	
				}
				main.SkipTaskbarHint = false;
			}
			if (advwin!=null){
				if (advwin.Visible){
					advwin.Deiconify ();
				}else{
					advwin.Show ();	
				}
				advwin.SkipTaskbarHint = false;
			}
		}

		public static void SetConsoleWindowVisibility (bool visible, string title)
		{
			IntPtr hWnd;

			try {
				hWnd = FindWindow (null, title);
			}
            catch (EntryPointNotFoundException) {
				return;
			}
			
			if (hWnd != IntPtr.Zero) {
				if (!visible)
					ShowWindow (hWnd, 0);
				else
					ShowWindow (hWnd, 1);
			}
		}
	}
}
